package mysgoog.pattern.emptyPattern;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.*;

import mysgoog.board.Board;
import mysgoog.bot.*;
import mysgoog.gtp.*;
import mysgoog.pattern.Matcher;
import mysgoog.pattern.Storage.ValuePair;
import mysgoog.pattern.Storage.ValueTriple;
import mysgoog.pattern.Storage.VertexValue;
import mysgoog.util.BoardUtil;
/**
* @author Fu, Zhongyang
*/
public class EmptyPatternMatcher
{

    private final int patternBoardSize = 8;
    private final int patternBoardSizeNum = 64;
    private final int patternNum = 4;

    private final int LEFT_UP = 0;
    private final int RIGHT_UP = 1;
    private final int LEFT_DOWN = 2;
    private final int RIGHT_DOWN = 3;

    private int[][] patternPos = null;

    Map<Integer, Map<String, ValueTriple>> patternMap;
  
    
    public EmptyPatternMatcher()
    {
        patternMap = new HashMap<Integer, Map<String, ValueTriple>>();
        try {
			EmptyPatternLoader.load(patternMap);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}        
    }

	public List<ValueTriple> getMatch(Color[] board, Color player, List<ValueTriple> moves) {		
		for (int key:patternMap.keySet()){
			int r = key / Config.getBoardSize();
			int c = key % Config.getBoardSize();
			getMatch(r, c, patternMap.get(key), board, player, moves);
		}
		return moves;
	}
	
	
	
	private void getMatch(int row, int column, Map<String, ValueTriple> map, Color[] board, Color player, List<ValueTriple> moves){
		Color[] board90 = BoardUtil.rotateBoard(Config.getBoardSize(), Config.getBoardSize(), board, 90);
		Color[] board270 = BoardUtil.rotateBoard(Config.getBoardSize(), Config.getBoardSize(), board, 270);
		Color[] board180 = BoardUtil.rotateBoard(Config.getBoardSize(), Config.getBoardSize(), board, 180);
		
		for (int i = -1; i < Config.getBoardSize() - row; i++){
			for (int j = -1; j < Config.getBoardSize() - column; j++){
				String subBoard;				
				//System.out.println(i + " " + j + " " + row + " " + column + " ");
				subBoard = BoardUtil.getSubBoardString(i, j, row, column, board, player);	
				//System.out.println(subBoard);
				if (map.containsKey(subBoard)){		
					moves.add(				
							changeVertex(map.get(subBoard), i, j));
				}
				subBoard = BoardUtil.getSubBoardString(i, j, row, column, board90, player);
				if (map.containsKey(subBoard)){					
					moves.add(
							rotateVertex(
									changeVertex(map.get(subBoard), i, j),
									Config.getBoardSize(),
									90));
				}				
				subBoard = BoardUtil.getSubBoardString(i, j, row, column, board180, player);
				if (map.containsKey(subBoard)){					
					moves.add(
							rotateVertex(
									changeVertex(map.get(subBoard), i, j),
									Config.getBoardSize(),
									180));
				}
				subBoard = BoardUtil.getSubBoardString(i, j, row, column, board270, player);
				if (map.containsKey(subBoard)){					
					moves.add(
							rotateVertex(
									changeVertex(map.get(subBoard), i, j),
									Config.getBoardSize(),
									270));
				}							
							
			}
		}
	}
	
	
	private ValueTriple changeVertex(ValueTriple value, int x, int y){
		
		ValueTriple triple = new ValueTriple(value.x + x, value.y + y, value.firstValue, value.secondValue);
		triple.list.addAll(value.list);
		return triple;
	}
	
	
	private ValueTriple rotateVertex(ValueTriple v, int boardSize, int degree){		
		int tmp;
		switch (degree){
			case 0:
				break;
			case 90:
				tmp = v.y;
				v.y = boardSize - 1 - v.x;
				v.x = tmp;				
				for (Vertex vertex:v.list){
					tmp = vertex.y;
					vertex.y = boardSize - 1 - vertex.x;
					vertex.x = tmp;		
				}
				break;
			case 180:
				v.y = boardSize - 1 - v.y;
				v.x = boardSize - 1 - v.x;
				for (Vertex vertex:v.list){
					tmp = vertex.y;
					vertex.y = boardSize - 1 - vertex.y;
					vertex.x = boardSize - 1 - vertex.x;		
				}
				break;
			case 270:
				tmp = v.y;
				v.y = v.x;
				v.x = boardSize - 1 - v.y;
				for (Vertex vertex:v.list){
					tmp = vertex.y;
					vertex.y = vertex.x;
					vertex.x = boardSize - 1 - vertex.y;		
				}
				break;
		}

		return v;
	}	
	
		
}
